home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / games / IndiZone / vroom / ogl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  53.9 KB  |  2,287 lines

  1. /*
  2.  * Copyright (C) 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <unistd.h>
  20. #include <math.h>
  21. #include <sys/time.h>
  22.  
  23. #include <X11/Intrinsic.h>
  24. #include <X11/StringDefs.h>
  25. #include <Xm/Xm.h>
  26.  
  27. #include <GL/glx.h>
  28. #include <GL/GLwMDrawA.h>
  29.  
  30. #include "ogl.h"
  31. #include "vroom.h"
  32. #include "body.h"
  33. #include "car.h"
  34. #include "track.h"
  35. #include "straight.h"
  36. #include "solo.h"
  37. #include "framerate.h"
  38. #include "playmode.h"
  39. #include "sound.h"
  40. #include "quickcull.h"
  41.  
  42. #define    DEG_2_RAD    ((float)0.017453293)
  43.  
  44. typedef struct {
  45.     short        ascent ;
  46.     short        descent ;
  47.     XFontStruct    *xfont ;
  48.     int        base ;
  49.     } VroomFont ;
  50.  
  51.  
  52. /* BEGIN PROTOTYPES -S ogl.c */
  53. static void             beginOverlay( void ) ;
  54. static void             changeLod( Widget w, XEvent *event, String *params,
  55.                             Cardinal *numParams ) ;
  56. static void             changeSpeed( Widget w, XEvent *event, String *params,
  57.                             Cardinal *numParams ) ;
  58. static void             changeView( Widget w, XEvent *event, String *params,
  59.                             Cardinal *numParams ) ;
  60. static void             changeVolume( int direction ) ;
  61. static void             commonOglInit( void ) ;
  62. static VroomFont *      createFont( Widget w, char *resource,
  63.                             int defaultHeight ) ;
  64. static void             createStars( void ) ;
  65. static void             drawIcons( char *position ) ;
  66. static void             drawIntroCB( Widget w, GLXContext *glc,
  67.                             GLwDrawingAreaCallbackStruct *cbs ) ;
  68. static void             drawPreviewCB( Widget w, XtPointer clientData,
  69.                             GLwDrawingAreaCallbackStruct *cbs ) ;
  70. static void             endOverlay( void ) ;
  71. static void             endSolo( Widget w, XEvent *event, String *params,
  72.                             Cardinal *numParams ) ;
  73. static XFontStruct *    findFont( Widget w, char *resource,
  74.                             int defaultHeight ) ;
  75. static int              getStrWidth( VroomFont *vf, char *str, int len ) ;
  76. static void             giveUp( Widget w, XEvent *event, String *params,
  77.                             Cardinal *numParams ) ;
  78. static void             initIntroCB( Widget w, XtPointer clientData,
  79.                             GLwDrawingAreaCallbackStruct *cbs ) ;
  80. static void             initMainCB( Widget w, XtPointer clientData,
  81.                             GLwDrawingAreaCallbackStruct *cbs ) ;
  82. static void             initPreviewCB( Widget w, XtPointer clientData,
  83.                             GLwDrawingAreaCallbackStruct *cbs ) ;
  84. static void             introDraw( void ) ;
  85. static void             laneChangeLeft( Widget w, XEvent *event,
  86.                             String *params, Cardinal *numParams ) ;
  87. static void             laneChangeRight( Widget w, XEvent *event,
  88.                             String *params, Cardinal *numParams ) ;
  89. static void             quit( Widget w, XEvent *event, String *params,
  90.                             Cardinal *numParams ) ;
  91. static void             resetView( void ) ;
  92. static void             resizeIntroCB( Widget w, GLXContext *glc,
  93.                             GLwDrawingAreaCallbackStruct *cbs ) ;
  94. static void             resizeMainCB( Widget w, XtPointer clientData,
  95.                             GLwDrawingAreaCallbackStruct *cbs ) ;
  96. static void             resizePreviewCB( Widget w, XtPointer clientData,
  97.                             GLwDrawingAreaCallbackStruct *cbs ) ;
  98. static void             setUpCull( void ) ;
  99. static void             showArrow( void ) ;
  100. static void             showFrameRate( void ) ;
  101. static void             showHelp( Widget w, XEvent *event, String *params,
  102.                             Cardinal *numParams ) ;
  103. static void             showPlayers( Widget w, XEvent *event, String *params,
  104.                             Cardinal *numParams ) ;
  105. static void             showRestartInfo( void ) ;
  106. static void             timeDraw( Widget w, XEvent *event, String *params,
  107.                             Cardinal *numParams ) ;
  108. static void             toggleBars( Widget w, XEvent *event, String *params,
  109.                             Cardinal *numParams ) ;
  110. static void             toggleDebug( Widget w, XEvent *event, String *params,
  111.                             Cardinal *numParams ) ;
  112. static void             toggleTime( Widget w, XEvent *event, String *params,
  113.                             Cardinal *numParams ) ;
  114. static void             volumeDown( Widget w, XEvent *event, String *params,
  115.                             Cardinal *numParams ) ;
  116. static void             volumeUp( Widget w, XEvent *event, String *params,
  117.                             Cardinal *numParams ) ;
  118. /* END PROTOTYPES -S ogl.c */
  119.  
  120. int            baseLod = 0 ;
  121. int            debugOn = 0 ;
  122. int            updateStatWindow ;
  123. Track            *introTrack[2] ;
  124. Widget            mainOgl ;
  125. Widget            previewOgl ;
  126.  
  127. extern char        *basename ;
  128. extern int        playMode ;
  129. extern int        freeTime ;
  130. extern int        steering ;
  131. extern int        self ;
  132. extern int        nCars ;
  133. extern int        isRobot[] ;
  134. extern int        showSpeedBars ;
  135. extern long        myHostId ;
  136. extern long        gameServerId ;
  137. extern float        currentTime ;
  138. extern float        frameRate ;
  139. extern GLuint        trackOutline ;
  140. extern GLfloat        carColors[][3] ;
  141. extern Car        cars[] ;
  142. extern PlayerStruct    player[] ;
  143. extern XtAppContext    appContext ;
  144. extern Sfx        alertSfx ;
  145. extern Sfx        changeLaneSfx ;
  146.  
  147. static char        *qualifyMsg = "Qualifying run." ;
  148. static int        nRenders = 0 ;
  149. static int        rearView ;
  150. static int        mouseX = 0 ;
  151. static int        mouseY = 0 ;
  152. static int        nDrawings[MAX_LOD] ;
  153. static float        drawingTime[MAX_LOD] ;
  154. static float        fontDy ;
  155. static float        fontY ;
  156. static float        qualifyMsgWidth ;
  157. static GLfloat        lightLoc[] = { 3.2, 0.2, 10.0, 0.0 } ;
  158. static GLfloat        lead ;
  159. static GLfloat        cosAzim ;
  160. static GLfloat        cosIncl ;
  161. static GLfloat        sinIncl ;
  162. static GLuint        lapRecord ;
  163. static GLuint        raceRecord ;
  164. static GLuint        qmBox ;
  165. static GLuint        instructions ;
  166. static GLuint        mainSet ;
  167. static GLuint        mapSet ;
  168. static GLuint        mapCar ;
  169. static GLuint        arrow ;
  170. static GLuint        speedBars ;
  171. static GLuint        icon[4] ;
  172. static GLuint        stars ;
  173. static GLfloat        raceViewW = 0.0 ;
  174. static GLfloat        raceViewH = 0.0 ;
  175. static GLdouble        raceViewWd = 0.0 ;
  176. static GLdouble        raceViewHd = 0.0 ;
  177. static GLXContext    mainGlc = NULL ;
  178. static GLXContext    introGlc = NULL ;
  179. static GLXContext    previewGlc = NULL ;
  180. static Widget        introOgl ;
  181. static VroomFont    *olf ;
  182. static GLubyte        mapCarRaster[] = { 0xf8, 0xf8, 0xf8, 0xf8, 0xf8 } ;
  183.  
  184. static GLubyte        skullRaster[4*32] = {
  185.                 0x00,0x00,0x00,0x00, 0x1c,0x00,0x00,0x38,
  186.                 0x1c,0x00,0x00,0x38, 0x3c,0x00,0x00,0x3c,
  187.                 0x3f,0x00,0x00,0xfc, 0x3b,0xc0,0x03,0xdc,
  188.                 0x00,0xf0,0x0f,0x00, 0x00,0x3c,0x3c,0x00,
  189.                 0x00,0x0f,0xf0,0x00, 0x00,0x03,0xc0,0x00,
  190.                 0x00,0x0f,0xf0,0x00, 0x00,0x3c,0x3c,0x00,
  191.                 0x00,0xf0,0x0f,0x00, 0x3b,0xc0,0x03,0xdc,
  192.                 0x3f,0x00,0x00,0xfc, 0x3c,0x07,0xe0,0x3c,
  193.                 0x1c,0x0f,0xf0,0x38, 0x1c,0x0f,0xf0,0x38,
  194.                 0x00,0x0f,0xf0,0x00, 0x00,0x1e,0x78,0x00,
  195.                 0x00,0x3e,0x7c,0x00, 0x00,0x3f,0xfc,0x00,
  196.                 0x00,0x7f,0xfe,0x00, 0x00,0xfb,0xdf,0x00,
  197.                 0x00,0xf1,0x8f,0x00, 0x00,0xf1,0x8f,0x00,
  198.                 0x00,0xfb,0xdf,0x00, 0x00,0xff,0xff,0x00,
  199.                 0x00,0xff,0xff,0x00, 0x00,0x7f,0xfe,0x00,
  200.                 0x00,0x3f,0xfc,0x00, 0x00,0x0f,0xf0,0x00,
  201.                 } ;
  202. static GLubyte        finishRaster[4*32] = {
  203.                 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
  204.                 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
  205.                 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
  206.                 0x00,0x00,0x00,0x00, 0x03,0x00,0x00,0xc0,
  207.                 0x01,0x80,0x01,0x80, 0x00,0xc0,0x03,0x00,
  208.                 0x00,0x60,0x06,0x00, 0x00,0x30,0x0c,0x00,
  209.                 0x02,0x18,0x18,0x40, 0x07,0x0c,0x30,0xe0,
  210.                 0x0f,0x86,0x61,0xf0, 0x1f,0xc3,0xc3,0xf8,
  211.                 0x3f,0xe1,0x87,0xfc, 0x7f,0xf3,0xcf,0xfe,
  212.                 0xff,0xfe,0x7f,0xff, 0x7f,0xfc,0x3f,0xfe,
  213.                 0x3f,0xf8,0x1f,0xfc, 0x1f,0xf0,0x0f,0xf8,
  214.                 0x0f,0xe0,0x07,0xf0, 0x07,0xc0,0x03,0xe0,
  215.                 0x03,0x80,0x01,0xc0, 0x01,0x00,0x00,0x80,
  216.                 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
  217.                 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
  218.                 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
  219.                 } ;
  220. static GLubyte        okRaster[4*32] = {
  221.                 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
  222.                 0x00,0x03,0xe0,0x00, 0x00,0x1f,0xfc,0x00,
  223.                 0x00,0x3c,0x1e,0x00, 0x00,0xe0,0x83,0x80,
  224.                 0x00,0xc8,0x89,0x80, 0x01,0x84,0x90,0xc0,
  225.                 0x03,0x00,0x00,0x60, 0x03,0x40,0x01,0x60,
  226.                 0x03,0x20,0x02,0x60, 0x06,0x00,0x00,0x30,
  227.                 0x06,0x01,0xc0,0x30, 0x06,0xe3,0xc3,0xb0,
  228.                 0x06,0x03,0xc0,0x30, 0x06,0x07,0x80,0x30,
  229.                 0x03,0x2e,0x02,0x60, 0x03,0x5c,0x01,0x60,
  230.                 0x03,0x18,0x00,0x60, 0x01,0x84,0x90,0xc0,
  231.                 0x00,0xc8,0x89,0x80, 0x00,0xe0,0x83,0x80,
  232.                 0x00,0x3c,0x1e,0x00, 0x00,0x1f,0xfc,0x00,
  233.                 0x00,0x07,0xf0,0x00, 0x00,0x01,0xc0,0x00,
  234.                 0x00,0x01,0xc0,0x00, 0x00,0x07,0xf0,0x00,
  235.                 0x00,0x07,0xf0,0x00, 0x00,0x03,0xe0,0x00,
  236.                 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
  237.                 } ;
  238.  
  239. static char        *instructionMsgs[] = {
  240.                 "Left mouse button - change 1 lane left.",
  241.                 "Right mouse button - change 1 lane right.",
  242.                 "Mouse up and down - adjust speed.",
  243.                 "Hit 'h' for detailed help.",
  244.                 } ;
  245.  
  246. static GLfloat        white[3] = { 1.0f, 1.0f, 1.0f } ;
  247. static GLfloat        black[3] = { 0.0f, 0.0f, 0.0f } ;
  248.  
  249. static XtActionsRec    actionsTable[] = {
  250.             { "quit",        quit },
  251.             { "laneChangeLeft",    laneChangeLeft },
  252.             { "laneChangeRight",    laneChangeRight },
  253.             { "changeSpeed",    changeSpeed },
  254.             { "changeView",        changeView },
  255.             { "changeLod",        changeLod },
  256.             { "giveUp",        giveUp },
  257.             { "showHelp",        showHelp },
  258.             { "showPlayers",    showPlayers },
  259.             { "toggleBars",        toggleBars },
  260.             { "volumeUp",        volumeUp },
  261.             { "volumeDown",        volumeDown },
  262. #ifdef DEBUG
  263.             { "endSolo",        endSolo },
  264.             { "toggleDebug",    toggleDebug },
  265.             { "toggleTime",        toggleTime },
  266.             { "timeDraw",        timeDraw },
  267. #endif /* DEBUG */
  268.             } ;
  269.  
  270. static char oglTranslations[] =
  271.     "<KeyDown>osfCancel:    quit() \n"
  272.     "<Btn3Down>:        laneChangeRight() \n"
  273.     "<Btn1Down>:        laneChangeLeft() \n"
  274.     "<Motion>:        changeSpeed() \n"
  275.     "Alt<KeyDown>d:        changeLod() \n"
  276.     "Alt<KeyDown>g:        giveUp() \n"
  277.     "<KeyDown>h:        showHelp() \n"
  278.     "<KeyDown>i:        showPlayers() \n"
  279.     "<KeyDown>v:        changeView() \n"
  280.     "<KeyDown>b:        toggleBars() \n"
  281.     "<KeyDown>osfUp:    volumeUp() \n"
  282.     "<KeyDown>osfDown:    volumeDown() \n"
  283. #ifdef DEBUG
  284.     "Alt<KeyDown>x:        endSolo() \n"
  285.     "<KeyDown>d:        toggleDebug() \n"
  286.     "<KeyDown>t:        timeDraw() \n"
  287.     "<KeyDown>f:        toggleTime() \n"
  288. #endif /* DEBUG */
  289.     ;
  290.  
  291. static GLfloat    poly1[4][3] = {
  292.             { -0.5f, -0.5f, 0.0f },
  293.             {  0.5f, -0.5f, 0.0f },
  294.             {  0.5f,  0.5f, 0.0f },
  295.             { -0.5f,  0.5f, 0.0f },
  296.             } ;
  297. static GLfloat    norm1[3] = { 0.0f, 0.0f, 1.0f } ;
  298. static GLfloat    color1[4][3] = {
  299.             { 1.0f, 0.0f, 0.0f },
  300.             { 1.0f, 1.0f, 0.0f },
  301.             { 0.0f, 1.0f, 0.0f },
  302.             { 0.0f, 1.0f, 1.0f },
  303.             } ;
  304.  
  305.  
  306. /*------------------------------------------------------------------------------
  307.  * Translation callback to exit program.
  308.  *----------------------------------------------------------------------------*/
  309. static void
  310. quit(
  311.     Widget        w,
  312.     XEvent        *event,
  313.     String        *params,
  314.     Cardinal    *numParams
  315.     )
  316. {
  317.     exitCB( w, NULL, NULL ) ;
  318. }
  319.  
  320.  
  321.  
  322. /*------------------------------------------------------------------------------
  323.  * Translation callback when mouse moves to change speed.
  324.  *----------------------------------------------------------------------------*/
  325. static void
  326. changeSpeed(
  327.     Widget        w,
  328.     XEvent        *event,
  329.     String        *params,
  330.     Cardinal    *numParams
  331.     )
  332. {
  333.     int    my ;
  334.  
  335.     my = event->xmotion.y ;
  336.  
  337.     cars[self].desiredSpeed = ( 1.0f - (float)my / raceViewH ) * TOP_SPEED ;
  338. }
  339.  
  340.  
  341.  
  342. /*------------------------------------------------------------------------------
  343.  * Draw routine.
  344.  *----------------------------------------------------------------------------*/
  345. void
  346. drawIt(
  347.     int    startCar
  348.     )
  349. {
  350.     int    i ;
  351.  
  352.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
  353.  
  354.  
  355.     /*
  356.      * Draw main window.
  357.      */
  358.     glCallList( mainSet ) ;
  359.  
  360.     glRotatef( -player[self].headingDeg, 0.0f, 0.0f, 1.0f ) ;
  361.     glCallList( stars + baseLod ) ;
  362.     glLightfv( GL_LIGHT0, GL_POSITION, lightLoc ) ;
  363.     glTranslatef( -player[self].x, -player[self].y, 0.0f ) ;
  364.  
  365.     setUpCull() ;
  366.  
  367.     drawTrack() ;
  368.  
  369.     glEnable( GL_DEPTH_TEST ) ;
  370.     glShadeModel( GL_SMOOTH ) ;
  371.  
  372.     cullDrawAllCars( startCar, nCars ) ;
  373.  
  374.     glShadeModel( GL_FLAT ) ;
  375.     glDisable( GL_DEPTH_TEST ) ;
  376.  
  377.     /*
  378.      * Draw map window.
  379.      */
  380.     glCallList( mapSet ) ;
  381.     for( i = startCar ; i < startCar + nCars ; i++ )
  382.     {
  383.         glColor3fv( player[i].color ) ;
  384.         glRasterPos2f( player[i].x, player[i].y ) ;
  385.         glCallList( mapCar ) ;
  386.     }
  387.  
  388.     /*
  389.      * Restore push and mode change done in mapSet display list.
  390.      */
  391.     glPopMatrix() ;
  392.     glMatrixMode( GL_MODELVIEW ) ;
  393. }
  394.  
  395.  
  396.  
  397. /*------------------------------------------------------------------------------
  398.  * Callback for initialization - create GLXContext.
  399.  *----------------------------------------------------------------------------*/
  400. static void
  401. initMainCB(
  402.     Widget                w,
  403.     XtPointer            clientData,
  404.     GLwDrawingAreaCallbackStruct    *cbs
  405.     )
  406. {
  407.     int        n ;
  408.     int        maxW ;
  409.     int        wid ;
  410.     Arg        args[1] ;
  411.     XVisualInfo    *vi ;
  412.  
  413.     /*
  414.      * Get GLXContext.
  415.      */
  416.     n = 0 ;
  417.     XtSetArg( args[n], GLwNvisualInfo, &vi ) ; n++ ;
  418.     XtGetValues( w, args, n ) ;
  419.  
  420.     mainGlc = glXCreateContext( XtDisplay( w ), vi, introGlc, GL_TRUE ) ;
  421.     GLwDrawingAreaMakeCurrent( w, mainGlc ) ;
  422.  
  423.     glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ) ;
  424.     glClearDepth( 1.0f ) ;
  425.     glClear( GL_COLOR_BUFFER_BIT ) ;
  426.     GLwDrawingAreaSwapBuffers( w ) ;
  427.  
  428.     glEnable( GL_DEPTH_TEST ) ;
  429.  
  430.     commonOglInit() ;
  431.  
  432.     olf = createFont( w, "*overlayFont", 18 ) ;
  433.     qualifyMsgWidth = (float)getStrWidth( olf, qualifyMsg,
  434.                         strlen( qualifyMsg ) ) ;
  435.     fontDy = (float)olf->ascent + (float)olf->descent + 1.0f ;
  436.     glListBase( olf->base ) ;
  437.  
  438.     lapRecord = glGenLists( 1 ) ;
  439.     raceRecord = glGenLists( 1 ) ;
  440.  
  441.     qmBox = glGenLists( 1 ) ;
  442.     glNewList( qmBox, GL_COMPILE ) ;
  443.     glColor3fv( black ) ;
  444.     glBegin( GL_TRIANGLE_STRIP ) ;
  445.     glVertex2f( -10.0f, olf->ascent + 10.0f ) ;
  446.     glVertex2f( -10.0f, -olf->descent - 10.0f ) ;
  447.     glVertex2f( 10.0f + qualifyMsgWidth, olf->ascent + 10.0f ) ;
  448.     glVertex2f( 10.0f + qualifyMsgWidth, -olf->descent - 10.0f ) ;
  449.     glEnd() ;
  450.     glColor3fv( white ) ;
  451.     glLineWidth( 3.0f ) ;
  452.     glBegin( GL_LINE_LOOP ) ;
  453.     glVertex2f( -10.0f, olf->ascent + 10.0f ) ;
  454.     glVertex2f( -10.0f, -olf->descent - 10.0f ) ;
  455.     glVertex2f( 10.0f + qualifyMsgWidth, -olf->descent - 10.0f ) ;
  456.     glVertex2f( 10.0f + qualifyMsgWidth, olf->ascent + 10.0f ) ;
  457.     glEnd() ;
  458.     glLineWidth( 1.0f ) ;
  459.     glEndList() ;
  460.  
  461.     instructions = glGenLists( 1 ) ;
  462.     glNewList( instructions, GL_COMPILE ) ;
  463.     maxW = 0 ;
  464.     for( n = 0 ; n < XtNumber( instructionMsgs ) ; n++ )
  465.     {
  466.         wid = getStrWidth( olf, instructionMsgs[n],
  467.                     strlen( instructionMsgs[n] ) ) ;
  468.         if( wid > maxW )
  469.         {
  470.             maxW = wid ;
  471.         }
  472.     }
  473.     glEnable( GL_BLEND ) ;
  474.     glColor4f( 0.0f, 0.0f, 0.0f, 0.5f ) ;
  475.     glBegin( GL_TRIANGLE_STRIP ) ;
  476.     glVertex2f( -5.0f - 0.5f * maxW, n * fontDy + 10.0f ) ;
  477.     glVertex2f( -5.0f - 0.5f * maxW, 5.0f ) ;
  478.     glVertex2f( 5.0f + 0.5f * maxW, n * fontDy + 10.0f ) ;
  479.     glVertex2f( 5.0f + 0.5f * maxW, 5.0f ) ;
  480.     glEnd() ;
  481.     glDisable( GL_BLEND ) ;
  482.     glColor3fv( white ) ;
  483.     glBegin( GL_LINE_LOOP ) ;
  484.     glVertex2f( -5.0f - 0.5f * maxW, n * fontDy + 10.0f ) ;
  485.     glVertex2f( -5.0f - 0.5f * maxW, 5.0f ) ;
  486.     glVertex2f( 5.0f + 0.5f * maxW, 5.0f ) ;
  487.     glVertex2f( 5.0f + 0.5f * maxW, n * fontDy + 10.0f ) ;
  488.     glEnd() ;
  489.     glColor3f( 1.0f, 0.5f, 0.0f ) ;
  490.     fontY = 10.0f + ( n - 1 ) * fontDy + olf->descent ;
  491.     for( n = 0 ; n < XtNumber( instructionMsgs ) ; n++ )
  492.     {
  493.         wid = strlen( instructionMsgs[n] ) ;
  494.         glRasterPos2f( -0.5f *
  495.                 getStrWidth( olf, instructionMsgs[n], wid ),
  496.                 fontY );
  497.         glCallLists( wid, GL_UNSIGNED_BYTE,
  498.                 instructionMsgs[n] ) ;
  499.         fontY -= fontDy ;
  500.     }
  501.     glEndList() ;
  502.  
  503.     speedBars = glGenLists( 1 ) ;
  504.  
  505.     /*
  506.      * Set viewport and initialize viewing matrix.
  507.      */
  508.     resizeMainCB( w, 0, cbs ) ;
  509.  
  510.     /*
  511.      * Create bitmap for cars in map window.
  512.      */
  513.     glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ) ;
  514.     mapCar = glGenLists( 1 ) ;
  515.     glNewList( mapCar, GL_COMPILE ) ;
  516.     glBitmap( 5, 5, 1.0f, 1.0f, 0.0f, 0.0f, mapCarRaster ) ;
  517.     glEndList() ;
  518.  
  519.     icon[0] = glGenLists( 3 ) ;
  520.     icon[1] = icon[0] + 1 ;
  521.     icon[2] = icon[0] + 2 ;
  522.     icon[3] = icon[2] ;
  523.     glNewList( icon[0], GL_COMPILE ) ;
  524.     glBitmap( 32, 32, 32.0f, 0.0f, 0.0f, 32.0f, okRaster ) ;
  525.     glEndList() ;
  526.     glNewList( icon[1], GL_COMPILE ) ;
  527.     glBitmap( 32, 32, 32.0f, 0.0f, 0.0f, 32.0f, skullRaster ) ;
  528.     glEndList() ;
  529.     glNewList( icon[2], GL_COMPILE ) ;
  530.     glBitmap( 32, 32, 32.0f, 0.0f, 0.0f, 32.0f, finishRaster ) ;
  531.     glEndList() ;
  532.  
  533.     /*
  534.      * Create arrow object.
  535.      */
  536.     arrow = glGenLists( 1 ) ;
  537.     glNewList( arrow, GL_COMPILE ) ;
  538.     glColor3fv( white ) ;
  539.     glBegin( GL_TRIANGLES ) ;
  540.     glVertex3f( 0.0f, 0.0f, 60.0f ) ;
  541.     glVertex3f( 30.0f, 0.0f, 90.0f ) ;
  542.     glVertex3f( -30.0f, 0.0f, 90.0f ) ;
  543.     glEnd() ;
  544.     glBegin( GL_TRIANGLE_STRIP ) ;
  545.     glVertex3f( -10.0f, 0.0f, 89.0f ) ;
  546.     glVertex3f( 10.0f, 0.0f, 89.0f ) ;
  547.     glVertex3f( -10.0f, 0.0f, 150.0f ) ;
  548.     glVertex3f( 10.0f, 0.0f, 150.0f ) ;
  549.     glEnd() ;
  550.     glColor3fv( black ) ;
  551.     glLineWidth( 3.0f ) ;
  552.     glBegin( GL_LINE_LOOP ) ;
  553.     glVertex3f( 0.0f, 0.0f, 60.0f ) ;
  554.     glVertex3f( 30.0f, 0.0f, 90.0f ) ;
  555.     glVertex3f( 10.0f, 0.0f, 90.0f ) ;
  556.     glVertex3f( 10.0f, 0.0f, 150.0f ) ;
  557.     glVertex3f( -10.0f, 0.0f, 150.0f ) ;
  558.     glVertex3f( -10.0f, 0.0f, 90.0f ) ;
  559.     glVertex3f( -30.0f, 0.0f, 90.0f ) ;
  560.     glEnd() ;
  561.     glLineWidth( 1.0f ) ;
  562.     glEndList() ;
  563.  
  564.     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
  565.     glDisable( GL_BLEND ) ;
  566.  
  567.     /*
  568.      * Initialize the viewing angle.
  569.      */
  570.     resetView() ;
  571. }
  572.  
  573.  
  574.  
  575. /*------------------------------------------------------------------------------
  576.  * Callback when resize occurs.
  577.  *----------------------------------------------------------------------------*/
  578. static void
  579. resizeMainCB(
  580.     Widget                w,
  581.     XtPointer            clientData,
  582.     GLwDrawingAreaCallbackStruct    *cbs
  583.     )
  584. {
  585.     int        n ;
  586.     GLfloat        x ;
  587.     GLfloat        y ;
  588.     GLfloat        bnds[8] ;
  589.     GLfloat        d ;
  590.     Window        rootWin ;
  591.     Window        childWin ;
  592.     int        rootX ;
  593.     int        rootY ;
  594.     int        winX ;
  595.     int        winY ;
  596.     unsigned int    mask ;
  597.     static int    init = 0 ;
  598.  
  599.     GLwDrawingAreaMakeCurrent( w, mainGlc ) ;
  600.  
  601.     if( init == 0 )
  602.     {
  603.         init = 1 ;
  604.         mainSet = glGenLists( 1 ) ;
  605.         mapSet = glGenLists( 1 ) ;
  606.     }
  607.  
  608.     raceViewW = (float)cbs->width ;
  609.     raceViewH = (float)cbs->height ;
  610.     raceViewWd = (double)raceViewW ;
  611.     raceViewHd = (double)raceViewH ;
  612.  
  613.     glViewport( 0, 0, cbs->width, cbs->height ) ;
  614.  
  615.     /*
  616.      * Set up main view matrix.
  617.      */
  618.     glMatrixMode( GL_PROJECTION ) ;
  619.     glLoadIdentity() ;
  620.     x = raceViewW / raceViewH ;
  621.     y = 1.0f ;
  622.     glFrustum( -x, x, -y, y, 2.0f, 4000.0f ) ;
  623.     glMatrixMode( GL_MODELVIEW ) ;
  624.     qcInit( x, y, 2.0f, 4000.0f ) ;
  625.  
  626.     /*
  627.      * Set up matrix for map overview.
  628.      */
  629.     glNewList( mapSet, GL_COMPILE ) ;
  630.     glLoadIdentity() ;
  631.     glMatrixMode( GL_PROJECTION ) ;
  632.     glPushMatrix() ;
  633.     glLoadIdentity() ;
  634.  
  635.     getTrackBounds( bnds ) ;
  636.     bnds[6] += 4.0f * LANE_WIDTH ;
  637.     bnds[7] += 4.0f * LANE_WIDTH ;
  638.     bnds[1] = bnds[4] + bnds[6] ;
  639.     bnds[3] = bnds[5] + bnds[7] ;
  640.     d = MAXFUNC( bnds[6], bnds[7] ) ;
  641.     bnds[0] = bnds[4] - ( x * 5.0f - 1.0f ) * d ;
  642.     bnds[2] = bnds[5] - ( y * 5.0f - 1.0f ) * d ;
  643.     glOrtho( bnds[0], bnds[1], bnds[2], bnds[3], -1.0, 1.0 ) ;
  644.     glCallList( trackOutline ) ;
  645.     glEndList() ;
  646.  
  647.     glLoadIdentity() ;
  648.  
  649.     /*
  650.      * Locate where the cursor is.
  651.      */
  652.     if( XQueryPointer( XtDisplay( w ), XtWindow( w ), &rootWin, &childWin,
  653.         &rootX, &rootY, &winX, &winY, &mask ) )
  654.     {
  655.         y = (float)winY / raceViewH ;
  656.         y = MINFUNC( 1.0f, y ) ;
  657.         y = MAXFUNC( 0.0f, y ) ;
  658.         cars[self].desiredSpeed = ( 1.0f - y ) * TOP_SPEED ;
  659.     }
  660.  
  661.     /*
  662.      * Create object for drawing speed bars.
  663.      */
  664.     x = 0.5f * raceViewW ;
  665.     glNewList( speedBars, GL_COMPILE ) ;
  666.     glBegin( GL_LINES ) ;
  667.     glVertex2f( x - 9.0f, 0.9f * raceViewH ) ;
  668.     glVertex2f( x + 9.0f, 0.9f * raceViewH ) ;
  669.     glVertex2f( x - 9.0f, 0.8f * raceViewH ) ;
  670.     glVertex2f( x + 9.0f, 0.8f * raceViewH ) ;
  671.     glVertex2f( x - 9.0f, 0.7f * raceViewH ) ;
  672.     glVertex2f( x + 9.0f, 0.7f * raceViewH ) ;
  673.     glVertex2f( x - 9.0f, 0.6f * raceViewH ) ;
  674.     glVertex2f( x + 9.0f, 0.6f * raceViewH ) ;
  675.     glVertex2f( x - 9.0f, 0.5f * raceViewH ) ;
  676.     glVertex2f( x + 9.0f, 0.5f * raceViewH ) ;
  677.     glEnd() ;
  678.     glEndList() ;
  679.  
  680. }
  681.  
  682.  
  683.  
  684. /*------------------------------------------------------------------------------
  685.  * Callback when resize occurs.
  686.  *----------------------------------------------------------------------------*/
  687. static void
  688. resizeIntroCB(
  689.     Widget                w,
  690.     GLXContext            *glc,
  691.     GLwDrawingAreaCallbackStruct    *cbs
  692.     )
  693. {
  694.     int        n ;
  695.     GLfloat        x ;
  696.     GLfloat        y ;
  697.  
  698.     GLwDrawingAreaMakeCurrent( w, *glc ) ;
  699.  
  700.     glMatrixMode( GL_PROJECTION ) ;
  701.     glLoadIdentity() ;
  702.     x = (float)cbs->width / (float)cbs->height ;
  703.     y = 1.0f ;
  704.     glFrustum( -x, x, -y, y, 2.0f, 4000.0f ) ;
  705.     glMatrixMode( GL_MODELVIEW ) ;
  706.     glViewport( 0, 0, cbs->width, cbs->height ) ;
  707. }
  708.  
  709.  
  710.  
  711. /*------------------------------------------------------------------------------
  712.  * Create the main OpenGL widget.
  713.  *----------------------------------------------------------------------------*/
  714. Widget
  715. createMainOglWidget(
  716.     Widget        parent,
  717.     Arg        pargs[],
  718.     int        pn
  719.     )
  720. {
  721.     int            n ;
  722.     Arg            args[15] ;
  723.     XtTranslations        transTable ;
  724.  
  725.     XtAppAddActions( appContext, actionsTable, XtNumber(actionsTable) ) ;
  726.  
  727.     transTable = XtParseTranslationTable( oglTranslations ) ;
  728.  
  729.     for( n = 0 ; n < pn ; n++ )
  730.     {
  731.         XtSetArg( args[n], pargs[n].name, pargs[n].value ) ;
  732.     }
  733.     XtSetArg( args[n], GLwNrgba, True ) ; n++ ;
  734.     XtSetArg( args[n], GLwNdoublebuffer, True ) ; n++ ;
  735.     XtSetArg( args[n], GLwNdepthSize, 16 ) ; n++ ;
  736.     XtSetArg( args[n], GLwNredSize, 1 ) ; n++ ;
  737.     XtSetArg( args[n], GLwNgreenSize, 1 ) ; n++ ;
  738.     XtSetArg( args[n], GLwNblueSize, 1 ) ; n++ ;
  739.     XtSetArg( args[n], GLwNinstallColormap, True ) ; n++ ;
  740.     mainOgl = XtCreateManagedWidget( "mainOgl", glwMDrawingAreaWidgetClass,
  741.                         parent, args, n ) ;
  742.     XtAddCallback( mainOgl, GLwNginitCallback, (XtCallbackProc)initMainCB,
  743.             NULL ) ;
  744.     XtAddCallback( mainOgl, GLwNresizeCallback,
  745.             (XtCallbackProc)resizeMainCB, NULL ) ;
  746.  
  747.     n = 0 ;
  748.     XtSetArg( args[n], XmNtranslations, transTable ) ; n++ ;
  749.     XtSetValues( mainOgl, args, n ) ;
  750.  
  751.     return( mainOgl ) ;
  752. }
  753.  
  754.  
  755.  
  756. /*------------------------------------------------------------------------------
  757.  * Reset the view.
  758.  *----------------------------------------------------------------------------*/
  759. static void
  760. resetView(
  761.     void
  762.     )
  763. {
  764.     float    azim ;
  765.     float    incl ;
  766.  
  767.     if( rearView )
  768.     {
  769.         azim = 180.0f ;
  770.         lead = 150.0f ;
  771.     }
  772.     else
  773.     {
  774.         azim = 0.0f ;
  775.         lead = -150.0f ;
  776.     }
  777.     incl = 35.0f ;
  778.  
  779.     cosAzim = cosf( azim * DEG_2_RAD ) ;
  780.  
  781.     cosIncl = cosf( incl * DEG_2_RAD ) ;
  782.     sinIncl = sinf( incl * DEG_2_RAD ) ;
  783.  
  784.     glNewList( mainSet, GL_COMPILE ) ;
  785.     glTranslatef( 0.0f, 0.0f, -750.0f ) ;
  786.     glRotatef( incl, 1.0f, 0.0f, 0.0f ) ;
  787.     glRotatef( azim, 0.0f, 1.0f, 0.0f ) ;
  788.     glRotatef( 90.0f, -1.0f, 0.0f, 0.0f ) ;
  789.     glTranslatef( 0.0f, lead, 0.0f ) ;
  790.     glEndList() ;
  791. }
  792.  
  793.  
  794.  
  795. /*------------------------------------------------------------------------------
  796.  * Time it.
  797.  *----------------------------------------------------------------------------*/
  798. static void
  799. timeDraw(
  800.     Widget        w,
  801.     XEvent        *event,
  802.     String        *params,
  803.     Cardinal    *numParams
  804.     )
  805. {
  806.     int        i ;
  807.     float        elapsed ;
  808.     int        nRenders = 72 ;
  809.     struct timeval    beginTime ;
  810.     struct timeval    endTime ;
  811.  
  812.     gettimeofday( &beginTime ) ;
  813.     glDrawBuffer( GL_FRONT ) ;
  814.     for( i = 0 ; i < nRenders ; i++ )
  815.     {
  816.         drawIt( 0 ) ;
  817.     }
  818.     glFinish() ;
  819.     glDrawBuffer( GL_BACK ) ;
  820.     gettimeofday( &endTime ) ;
  821.     if( endTime.tv_usec < beginTime.tv_usec)
  822.     {
  823.         endTime.tv_usec += 1000000 ;
  824.         endTime.tv_sec -= 1 ;
  825.     }
  826.     elapsed = (float)( endTime.tv_usec - beginTime.tv_usec ) / 1000000.0f
  827.             + (float)( endTime.tv_sec - beginTime.tv_sec ) ;
  828.  
  829.     printf( "elapsed time = %.2f seconds, %.2f frames/second\n",
  830.             elapsed, (float)nRenders/elapsed ) ;
  831. }
  832.  
  833.  
  834.  
  835. /*------------------------------------------------------------------------------
  836.  * Toggle speed bars on/off.
  837.  *----------------------------------------------------------------------------*/
  838. static void
  839. toggleBars(
  840.     Widget        w,
  841.     XEvent        *event,
  842.     String        *params,
  843.     Cardinal    *numParams
  844.     )
  845. {
  846.     showSpeedBars = !showSpeedBars ;
  847. }
  848.  
  849.  
  850.  
  851. /*------------------------------------------------------------------------------
  852.  * Toggle debug on/off.
  853.  *----------------------------------------------------------------------------*/
  854. static void
  855. toggleDebug(
  856.     Widget        w,
  857.     XEvent        *event,
  858.     String        *params,
  859.     Cardinal    *numParams
  860.     )
  861. {
  862.     debugOn = !debugOn ;
  863.     printf( "debug %s\n", debugOn ? "on" : "off" ) ;
  864. }
  865.  
  866.  
  867.  
  868. /*------------------------------------------------------------------------------
  869.  * Toggle freeTime on/off.
  870.  *----------------------------------------------------------------------------*/
  871. static void
  872. toggleTime(
  873.     Widget        w,
  874.     XEvent        *event,
  875.     String        *params,
  876.     Cardinal    *numParams
  877.     )
  878. {
  879.     if( freeTime )
  880.     {
  881.         freeTime = 0 ;
  882.     }
  883.     else
  884.     {
  885.         freeTime = 1 ;
  886.     }
  887. }
  888.  
  889.  
  890.  
  891. /*------------------------------------------------------------------------------
  892.  * Pop-up a help window.
  893.  *----------------------------------------------------------------------------*/
  894. static void
  895. showHelp(
  896.     Widget        w,
  897.     XEvent        *event,
  898.     String        *params,
  899.     Cardinal    *numParams
  900.     )
  901. {
  902.     showRaceHelpCB( w, NULL, NULL ) ;
  903. }
  904.  
  905.  
  906.  
  907. /*------------------------------------------------------------------------------
  908.  * Change between front and rear views.
  909.  *----------------------------------------------------------------------------*/
  910. static void
  911. changeView(
  912.     Widget        w,
  913.     XEvent        *event,
  914.     String        *params,
  915.     Cardinal    *numParams
  916.     )
  917. {
  918.     if( rearView )
  919.     {
  920.         rearView = 0 ;
  921.         setMessage( "Looking forward.\n" ) ;
  922.     }
  923.     else
  924.     {
  925.         rearView = 1 ;
  926.         setMessage( "Looking backward.\n" ) ;
  927.     }
  928.     resetView() ;
  929. }
  930.  
  931.  
  932.  
  933. /*------------------------------------------------------------------------------
  934.  * Increase the volume.
  935.  *----------------------------------------------------------------------------*/
  936. static void
  937. volumeUp(
  938.     Widget        w,
  939.     XEvent        *event,
  940.     String        *params,
  941.     Cardinal    *numParams
  942.     )
  943. {
  944.     changeVolume( 1 ) ;
  945. }
  946.  
  947.  
  948.  
  949. /*------------------------------------------------------------------------------
  950.  * Decrease the volume.
  951.  *----------------------------------------------------------------------------*/
  952. static void
  953. volumeDown(
  954.     Widget        w,
  955.     XEvent        *event,
  956.     String        *params,
  957.     Cardinal    *numParams
  958.     )
  959. {
  960.     changeVolume( -1 ) ;
  961. }
  962.  
  963.  
  964.  
  965. /*------------------------------------------------------------------------------
  966.  * Change the volume.
  967.  *----------------------------------------------------------------------------*/
  968. static void
  969. changeVolume(
  970.     int    direction
  971.     )
  972. {
  973.     setMessage( "Volume set to %d.", sfxVolumeChange( direction ) ) ;
  974.     sfxPlay( alertSfx ) ;
  975. }
  976.  
  977.  
  978.  
  979. /*------------------------------------------------------------------------------
  980.  * Change lanes to the left.
  981.  *----------------------------------------------------------------------------*/
  982. static void
  983. laneChangeLeft(
  984.     Widget        w,
  985.     XEvent        *event,
  986.     String        *params,
  987.     Cardinal    *numParams
  988.     )
  989. {
  990.     if( CAR_RACING( cars+self ) )
  991.     {
  992.         if( ( cars[self].status & CHANGE_LANES ) == 0 &&
  993.             ( playMode == VROOM_SOLO || gameServerId == myHostId ) )
  994.         {
  995.             sfxPlay( changeLaneSfx ) ;
  996.         }
  997.         cars[self].status &= ~CHANGE_LANE_RIGHT ;
  998.         cars[self].status |= CHANGE_LANE_LEFT ;
  999.         steering = cars[self].status & CHANGE_LANES ;
  1000.     }
  1001. }
  1002.  
  1003.  
  1004.  
  1005. /*------------------------------------------------------------------------------
  1006.  * Change lanes to the right.
  1007.  *----------------------------------------------------------------------------*/
  1008. static void
  1009. laneChangeRight(
  1010.     Widget        w,
  1011.     XEvent        *event,
  1012.     String        *params,
  1013.     Cardinal    *numParams
  1014.     )
  1015. {
  1016.     if( CAR_RACING( cars+self ) )
  1017.     {
  1018.         if( ( cars[self].status & CHANGE_LANES ) == 0 &&
  1019.             ( playMode == VROOM_SOLO || gameServerId == myHostId ) )
  1020.         {
  1021.             sfxPlay( changeLaneSfx ) ;
  1022.         }
  1023.         cars[self].status &= ~CHANGE_LANE_LEFT ;
  1024.         cars[self].status |= CHANGE_LANE_RIGHT ;
  1025.         steering = cars[self].status & CHANGE_LANES ;
  1026.     }
  1027. }
  1028.  
  1029.  
  1030.  
  1031. /*------------------------------------------------------------------------------
  1032.  * Determine the default level of detail
  1033.  *----------------------------------------------------------------------------*/
  1034. void
  1035. defaultLod(
  1036.     void
  1037.     )
  1038. {
  1039.     int        i ;
  1040.     float        fps ;
  1041.     static int    init = 0 ;
  1042.  
  1043.     if( init == 0 )
  1044.     {
  1045.         init = 1 ;
  1046.  
  1047. #ifdef DEBUG
  1048.         for( i = 0 ; i < MAX_LOD ; i++ )
  1049.         {
  1050.             if( drawingTime[i] > 0.0f )
  1051.             {
  1052.                 printf( "lod: %d fps = %.2f\n", i, 
  1053.                     (float)nDrawings[i] / drawingTime[i] ) ;
  1054.             }
  1055.             else
  1056.             {
  1057.                 printf( "lod: %d fps = ???\n", i ) ;
  1058.             }
  1059.         }
  1060. #endif /* DEBUG */
  1061.         for( i = 0 ; i < MAX_LOD - 1 ; i++ )
  1062.         {
  1063.             if( drawingTime[i] > 0.0f )
  1064.             {
  1065.                 fps = (float)nDrawings[i] / drawingTime[i] ;
  1066.                 if( fps > 15.0f )
  1067.                 {
  1068.                     break ;
  1069.                 }
  1070.             }
  1071.         }
  1072.  
  1073.         baseLod = i ;
  1074.     }
  1075.  
  1076.     setWorkProc( VROOM_WP_TIME_GRAPHICS, 0 ) ;
  1077. }
  1078.  
  1079.  
  1080.  
  1081. /*------------------------------------------------------------------------------
  1082.  * Time graphics to determine a default lod.
  1083.  *----------------------------------------------------------------------------*/
  1084. void
  1085. timeGraphics(
  1086.     void
  1087.     )
  1088. {
  1089.     int        i ;
  1090.     float        t0 ;
  1091.     static int    init = 0 ;
  1092.  
  1093.     if( init == 0 )
  1094.     {
  1095.         for( i = 0 ; i < MAX_LOD ; i++ )
  1096.         {
  1097.             nDrawings[i] = 0 ;
  1098.             drawingTime[i] = 0.0f ;
  1099.         }
  1100.         init = 1 ;
  1101.     }
  1102.  
  1103.     baseLod = ( nRenders / 10 ) % MAX_LOD ;
  1104.     glFinish() ;
  1105.     t0 = gameTime() ;
  1106.     introDraw() ;
  1107.     glFinish() ;
  1108.     sginap( 0 ) ;
  1109.     drawingTime[baseLod] += gameTime() - t0 ;
  1110.     nDrawings[baseLod] += 1 ;
  1111.     nRenders++ ;
  1112.  
  1113.     if( nRenders >= MAX_LOD * 100 )
  1114.     {
  1115.         setWorkProc( VROOM_WP_TIME_GRAPHICS, 0 ) ;
  1116.     }
  1117. }
  1118.  
  1119.  
  1120.  
  1121. /*------------------------------------------------------------------------------
  1122.  * Check for a graphics error.
  1123.  *----------------------------------------------------------------------------*/
  1124. void
  1125. checkGlError(
  1126.     char    *label
  1127.     )
  1128. {
  1129.     GLenum    err ;
  1130.  
  1131.     while( ( err = glGetError() ) != GL_NO_ERROR )
  1132.     {
  1133.         printf( "%s: err 0x%04x\n", label, (int)err ) ;
  1134.     }
  1135. }
  1136.  
  1137.  
  1138.  
  1139. /*------------------------------------------------------------------------------
  1140.  * Create the intro OpenGL widget.
  1141.  *----------------------------------------------------------------------------*/
  1142. void
  1143. createIntroOglWidget(
  1144.     Widget        parent,
  1145.     Arg        pargs[],
  1146.     int        pn
  1147.     )
  1148. {
  1149.     int            n ;
  1150.     Arg            args[15] ;
  1151.  
  1152.     for( n = 0 ; n < pn ; n++ )
  1153.     {
  1154.         XtSetArg( args[n], pargs[n].name, pargs[n].value ) ;
  1155.     }
  1156.     XtSetArg( args[n], GLwNrgba, True ) ; n++ ;
  1157.     XtSetArg( args[n], GLwNdoublebuffer, True ) ; n++ ;
  1158.     XtSetArg( args[n], GLwNdepthSize, 16 ) ; n++ ;
  1159.     XtSetArg( args[n], GLwNredSize, 1 ) ; n++ ;
  1160.     XtSetArg( args[n], GLwNgreenSize, 1 ) ; n++ ;
  1161.     XtSetArg( args[n], GLwNblueSize, 1 ) ; n++ ;
  1162.     XtSetArg( args[n], GLwNinstallColormap, True ) ; n++ ;
  1163.     introOgl = XtCreateManagedWidget( "introOgl",
  1164.                 glwMDrawingAreaWidgetClass, parent, args, n ) ;
  1165.     XtAddCallback( introOgl, GLwNexposeCallback,
  1166.                 (XtCallbackProc)drawIntroCB, &introGlc ) ;
  1167.     XtAddCallback( introOgl, GLwNginitCallback, (XtCallbackProc)initIntroCB,
  1168.             NULL ) ;
  1169.     XtAddCallback( introOgl, GLwNresizeCallback,
  1170.             (XtCallbackProc)resizeIntroCB, &introGlc ) ;
  1171.  
  1172.     baseLod = 0 ;
  1173.     setWorkProc( VROOM_WP_TIME_GRAPHICS, 1 ) ;
  1174. }
  1175.  
  1176.  
  1177.  
  1178. /*------------------------------------------------------------------------------
  1179.  * Callback for initialization - create GLXContext.
  1180.  *----------------------------------------------------------------------------*/
  1181. static void
  1182. initIntroCB(
  1183.     Widget                w,
  1184.     XtPointer            clientData,
  1185.     GLwDrawingAreaCallbackStruct    *cbs
  1186.     )
  1187. {
  1188.     int        n ;
  1189.     Arg        args[1] ;
  1190.     XVisualInfo    *vi ;
  1191.  
  1192.     /*
  1193.      * Get GLXContext.
  1194.      */
  1195.     n = 0 ;
  1196.     XtSetArg( args[n], GLwNvisualInfo, &vi ) ; n++ ;
  1197.     XtGetValues( w, args, n ) ;
  1198.  
  1199.     introGlc = glXCreateContext( XtDisplay( w ), vi, mainGlc, GL_TRUE ) ;
  1200.     GLwDrawingAreaMakeCurrent( w, introGlc ) ;
  1201.  
  1202.     glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ) ;
  1203.     glClearDepth( 1.0f ) ;
  1204.  
  1205.     glEnable( GL_DEPTH_TEST ) ;
  1206.  
  1207.     /*
  1208.      * Set viewport and initialize viewing matrix.
  1209.      */
  1210.     resizeIntroCB( w, &introGlc, cbs ) ;
  1211.  
  1212.     commonOglInit() ;
  1213.  
  1214.     introTrack[0] = createStartingTrack( 2, 800.0f ) ;
  1215.     introTrack[0]->x = 0.0f ;
  1216.     introTrack[0]->y = 0.0f ;
  1217.     introTrack[0]->theta = 0.0f ;
  1218.     introTrack[0]->number = 0 ;
  1219.     introTrack[0]->added( introTrack[0] ) ;
  1220.     introTrack[1] = createStraightTrack( 2, 800.0f ) ;
  1221.     introTrack[0]->add( introTrack[0], introTrack[1] ) ;
  1222.     introTrack[1]->number = 1 ;
  1223.     introTrack[1]->added( introTrack[1] ) ;
  1224.  
  1225.     setIntroCarShot() ;
  1226.  
  1227.     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
  1228.     glShadeModel( GL_FLAT ) ;
  1229.     glDisable( GL_DEPTH_TEST ) ;
  1230.     glDisable( GL_LIGHTING ) ;
  1231.     glDisable( GL_BLEND ) ;
  1232. }
  1233.  
  1234.  
  1235.  
  1236. /*------------------------------------------------------------------------------
  1237.  * Common graphics initialization that only needs to be done once.
  1238.  *----------------------------------------------------------------------------*/
  1239. static void
  1240. commonOglInit(
  1241.     void
  1242.     )
  1243. {
  1244.     static int    init = 0 ;
  1245.  
  1246.     /*
  1247.      * Define light position (accept default values for colors, etc.).
  1248.      */
  1249.     glLightfv( GL_LIGHT0, GL_POSITION, lightLoc ) ;
  1250.     glEnable( GL_LIGHT0 ) ;
  1251.  
  1252.     glShadeModel( GL_FLAT ) ;
  1253.     glDisable( GL_DEPTH_TEST ) ;
  1254.     glDisable( GL_LIGHTING ) ;
  1255.  
  1256.     glCullFace( GL_BACK ) ;
  1257.     glEnable( GL_CULL_FACE ) ;
  1258.  
  1259.         /*
  1260.          * Set to color calls change material diffuse property.
  1261.          */
  1262.         glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, 1 ) ;
  1263.         glColorMaterial( GL_FRONT, GL_DIFFUSE ) ;
  1264.  
  1265.     if( init )
  1266.     {
  1267.         return ;
  1268.     }
  1269.  
  1270.     init = 1 ;
  1271.  
  1272.     defineCarMaterials() ;
  1273.  
  1274.     /*
  1275.      * Build the car.
  1276.      */
  1277.     createCar() ;
  1278.  
  1279.     initCarColors() ;
  1280.  
  1281.     /*
  1282.      * Build background.
  1283.      */
  1284.     createStars() ;
  1285. }
  1286.  
  1287.  
  1288.  
  1289. /*------------------------------------------------------------------------------
  1290.  * Callback for redrawing the intro window.
  1291.  *----------------------------------------------------------------------------*/
  1292. static void
  1293. drawIntroCB(
  1294.     Widget                w,
  1295.     GLXContext            *glc,
  1296.     GLwDrawingAreaCallbackStruct    *cbs
  1297.     )
  1298. {
  1299.     int    realLod ;
  1300.  
  1301.     GLwDrawingAreaMakeCurrent( w, *glc ) ;
  1302.  
  1303.     glShadeModel( GL_FLAT ) ;
  1304.     glDisable( GL_DEPTH_TEST ) ;
  1305.     glDisable( GL_LIGHTING ) ;
  1306.  
  1307.     realLod = baseLod ;
  1308.     baseLod = 0 ;
  1309.     introDraw() ;
  1310.     baseLod = realLod ;
  1311.  
  1312.     GLwDrawingAreaSwapBuffers( w ) ;
  1313. }
  1314.  
  1315.  
  1316.  
  1317. /*------------------------------------------------------------------------------
  1318.  * Draw the title scene.
  1319.  *----------------------------------------------------------------------------*/
  1320. static void
  1321. introDraw(
  1322.     void
  1323.     )
  1324. {
  1325.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
  1326.  
  1327.     glLoadIdentity() ;
  1328.  
  1329.     glTranslatef( 0.0f, 0.0f, -235.0f ) ;
  1330.  
  1331.     glRotatef( 45.0f, 1.0f, 0.0f, 0.0f ) ;
  1332.  
  1333.     glRotatef( 165.0f, 0.0f, 1.0f, 0.0f ) ;
  1334.  
  1335.     glRotatef( 90.0f, -1.0f, 0.0f, 0.0f ) ;
  1336.  
  1337.     glCallList( stars + baseLod ) ;
  1338.  
  1339.     glTranslatef( -player[0].x, -player[0].y, 0.0f ) ;
  1340.  
  1341.     glCallList( introTrack[0]->drawMarkerList + baseLod ) ;
  1342.     glCallList( introTrack[1]->drawMarkerList + baseLod ) ;
  1343.     glColor3f( 0.4f, 0.4f, 0.4f ) ;
  1344.     glCallList( introTrack[0]->drawList + baseLod ) ;
  1345.     glCallList( introTrack[1]->drawList + baseLod ) ;
  1346.  
  1347.     glEnable( GL_LIGHTING ) ;
  1348.     glEnable( GL_DEPTH_TEST ) ;
  1349.     glShadeModel( GL_SMOOTH ) ;
  1350.  
  1351.     drawAllCars( 0, MAX_PLAYERS ) ;
  1352.  
  1353.     glShadeModel( GL_FLAT ) ;
  1354.     glDisable( GL_DEPTH_TEST ) ;
  1355.     glDisable( GL_LIGHTING ) ;
  1356. }
  1357.  
  1358.  
  1359.  
  1360. /*------------------------------------------------------------------------------
  1361.  * Create a font from an X string.
  1362.  *----------------------------------------------------------------------------*/
  1363. static VroomFont *
  1364. createFont(
  1365.     Widget    w,
  1366.     char    *resource,
  1367.     int    defaultHeight
  1368.     )
  1369. {
  1370.     int            i ;
  1371.     XFontStruct        *font ;
  1372.     GLenum            err ;
  1373.     VroomFont        *vf ;
  1374.  
  1375.     font = findFont( w, resource, defaultHeight ) ;
  1376.  
  1377.     vf = myMalloc( sizeof( VroomFont ) ) ;
  1378.     vf->base = glGenLists( 127 ) ;
  1379.     glXUseXFont( font->fid, 0, 127, vf->base ) ;
  1380.     if( ( err = glGetError() ) != GL_NO_ERROR )
  1381.     {
  1382.         printf( "err #%d\n", err ) ;
  1383.     }
  1384.  
  1385.     vf->ascent = font->max_bounds.ascent ;
  1386.     vf->descent = font->max_bounds.descent ;
  1387.     vf->xfont = font ;
  1388.  
  1389.     return( vf ) ;
  1390. }
  1391.  
  1392.  
  1393.  
  1394. /*------------------------------------------------------------------------------
  1395.  * Locate and load a font.
  1396.  *----------------------------------------------------------------------------*/
  1397. static XFontStruct *
  1398. findFont(
  1399.     Widget    w,
  1400.     char    *resource,
  1401.     int    defaultHeight
  1402.     )
  1403. {
  1404.     int            i ;
  1405.     int            delta ;
  1406.     int            k ;
  1407.     int            ibest ;
  1408.     XrmDatabase        db ;
  1409.     char            *fl ;
  1410.     XrmValue        value ;
  1411.     char            **fontList ;
  1412.     int            nFonts ;
  1413.     XFontStruct        *font ;
  1414.     XFontStruct        *fontInfo ;
  1415.     static char        *fontPattern = "-*-helvetica-bold-r-normal--*" ;
  1416.  
  1417.     value.addr = NULL ;
  1418.     db = XtDatabase( XtDisplay( w ) ) ;
  1419.     if( !XrmGetResource( db, resource, resource, &fl, &value ) 
  1420.         || ( font = XLoadQueryFont( XtDisplay( w ), value.addr ) )
  1421.         == NULL )
  1422.     {
  1423.         fprintf( stderr, "%s: could not load specified font, %s\n",
  1424.             basename, value.addr ) ;
  1425.         fontList = XListFontsWithInfo( XtDisplay( w ), fontPattern, 10,
  1426.                     &nFonts, &fontInfo ) ;
  1427.         if( nFonts == 0 )
  1428.         {
  1429.             fontList = XListFonts( XtDisplay( w ), "*", 1,
  1430.                         &nFonts ) ;
  1431.             if( nFonts == 0 )
  1432.             {
  1433.                 fatalError( "Can not load fonts!" ) ;
  1434.             }
  1435.             fprintf( stderr, "%s: defaulting to %s\n", basename,
  1436.                 fontList[0] ) ;
  1437.             font = XLoadQueryFont( XtDisplay( w ), fontList[0] ) ;
  1438.             XFreeFontNames( fontList ) ;
  1439.         }
  1440.         else
  1441.         {
  1442.             delta = fontInfo[0].ascent - fontInfo[0].descent ;
  1443.             k = delta ;
  1444.             ibest = 0 ;
  1445.             for( i = 1 ; i < nFonts ; i++ )
  1446.             {
  1447.                 delta = fontInfo[i].ascent -
  1448.                         fontInfo[i].descent ;
  1449.                 if( delta < k && k >= defaultHeight )
  1450.                 {
  1451.                     ibest = i ;
  1452.                     k = delta ;
  1453.                 }
  1454.                 else if( delta < defaultHeight && delta > k )
  1455.                 {
  1456.                     ibest = i ;
  1457.                     k = delta ;
  1458.                 }
  1459.             }
  1460.             fprintf( stderr, "%s: defaulting to %s\n", basename,
  1461.                 fontList[ibest] ) ;
  1462.             font = XLoadQueryFont( XtDisplay( w ),
  1463.                         fontList[ibest] ) ;
  1464.             XFreeFontInfo( fontList, fontInfo, nFonts ) ;
  1465.         }
  1466.     }
  1467.  
  1468.     return( font ) ;
  1469. }
  1470.  
  1471.  
  1472.  
  1473. /*------------------------------------------------------------------------------
  1474.  * Draw overlay for pre trial run.
  1475.  *----------------------------------------------------------------------------*/
  1476. void
  1477. drawPreTrialOverlay(
  1478.     float    t,
  1479.     char    position[],
  1480.     int    timeTrial,
  1481.     int    showRecord
  1482.     )
  1483. {
  1484.     char    *str ;
  1485.     int    i ;
  1486.     int    len ;
  1487.     float    g ;
  1488.     float    x ;
  1489.  
  1490.     showArrow() ;
  1491.  
  1492.     beginOverlay() ;
  1493.  
  1494.     str = raceTimeString( t, &len ) ;
  1495.  
  1496.     glCallLists( 11, GL_UNSIGNED_BYTE, "Countdown: "  ) ;
  1497.     glCallLists( len, GL_UNSIGNED_BYTE, str ) ;
  1498.  
  1499.     if( showRecord )
  1500.     {
  1501.         i = position[0] ;
  1502.         str = longRaceTimeString( cars[i].bestLapTime, &len ) ;
  1503.         fontY -= fontDy ;
  1504.         glRasterPos2f( 5.0f, fontY ) ;
  1505.         glCallLists( 18, GL_UNSIGNED_BYTE, "New lap record of " ) ;
  1506.         glCallLists( len, GL_UNSIGNED_BYTE, str ) ;
  1507.         glCallLists( 8, GL_UNSIGNED_BYTE, " set by " ) ;
  1508.         glCallLists( strlen( cars[i].name ), GL_UNSIGNED_BYTE,
  1509.                 cars[i].name ) ;
  1510.     }
  1511.  
  1512.     drawIcons( position ) ;
  1513.  
  1514.     /*
  1515.      * In projection matrix mode, can't use glPopMatrix here because
  1516.      * it may exceed the minimum projection matrix stack size dictacted
  1517.      * by OpenGL.
  1518.      */
  1519.     glTranslatef( 0.5f * raceViewW, 0.0f, 0.0f ) ;
  1520.     glCallList( instructions ) ;
  1521.     glTranslatef( -0.5f * raceViewW, 0.0f, 0.0f ) ;
  1522.  
  1523.     if( timeTrial )
  1524.     {
  1525.         g = fmodf( t, 2.0f ) - 1.0f ;
  1526.         x = 0.5f * ( raceViewW - qualifyMsgWidth ) ;
  1527.         fontY = 0.75f * raceViewH ;
  1528.         glTranslatef( x, fontY, 0.0f ) ;
  1529.         glCallList( qmBox ) ;
  1530.         glColor3f( 1.0f, ABSFUNC( g ), 0.0f ) ;
  1531.         glRasterPos2f( 0.0f, 0.0f ) ;
  1532.         glCallLists( 15, GL_UNSIGNED_BYTE, qualifyMsg ) ;
  1533.         glTranslatef( -x, -fontY, 0.0f ) ;
  1534.     }
  1535.  
  1536.     endOverlay() ;
  1537. }
  1538.  
  1539.  
  1540.  
  1541. /*------------------------------------------------------------------------------
  1542.  * Draw overlay for trial run.
  1543.  *----------------------------------------------------------------------------*/
  1544. void
  1545. drawTrialOverlay(
  1546.     float    t,
  1547.     char    position[]
  1548.     )
  1549. {
  1550.     char    *str ;
  1551.     int    len ;
  1552.     char    label[15] ;
  1553.  
  1554.     beginOverlay() ;
  1555.  
  1556.     sprintf( label, "Lap: %d", cars[self].lap ) ;
  1557.     glCallLists( 6, GL_UNSIGNED_BYTE, label ) ;
  1558.  
  1559.     fontY -= fontDy ;
  1560.     glRasterPos2f( 5.0f, fontY ) ;
  1561.     sprintf( label, "Time: " ) ;
  1562.     glCallLists( 6, GL_UNSIGNED_BYTE, label ) ;
  1563.     str = raceTimeString( t, &len ) ;
  1564.     glCallLists( len, GL_UNSIGNED_BYTE, str ) ;
  1565.  
  1566.     fontY -= fontDy ;
  1567.     glRasterPos2f( 5.0f, fontY ) ;
  1568.     glCallList( lapRecord ) ;
  1569.  
  1570. #ifdef DEBUG
  1571.     showFrameRate() ;
  1572. #endif /* DEBUG */
  1573.  
  1574.     if( cars[self].status & CAR_WIPE_OUT )
  1575.     {
  1576.         showRestartInfo() ;
  1577.     }
  1578.  
  1579.     drawIcons( position ) ;
  1580.  
  1581.     endOverlay() ;
  1582. }
  1583.  
  1584.  
  1585.  
  1586. /*------------------------------------------------------------------------------
  1587.  * Draw the status symbols.
  1588.  *----------------------------------------------------------------------------*/
  1589. static void
  1590. drawIcons(
  1591.     char    *position
  1592.     )
  1593. {
  1594.     int    i ;
  1595.     int    n ;
  1596.     float    y ;
  1597.  
  1598.     y = MAX_PLAYERS * 38.0f + 2.0f ;
  1599.     for( i = 0 ; i < MAX_PLAYERS ; i++ )
  1600.     {
  1601.         n = position[i] ;
  1602.         y -= 38.0f ;
  1603.         glColor3fv( carColors[n] ) ;
  1604.         glRasterPos2f( raceViewW - 2.0f, y ) ;
  1605.         glCallList( icon[cars[n].status & 0x03] ) ;
  1606.     }
  1607. }
  1608.  
  1609.  
  1610.  
  1611. /*------------------------------------------------------------------------------
  1612.  * Draw overlay for race.
  1613.  *----------------------------------------------------------------------------*/
  1614. void
  1615. drawRaceOverlay(
  1616.     float    t,
  1617.     int    laps,
  1618.     int    dLaps,
  1619.     int    ahead,
  1620.     char    position[]
  1621.     )
  1622. {
  1623.     char    *str ;
  1624.     int    len ;
  1625.     char    label[26] ;
  1626.  
  1627.     beginOverlay() ;
  1628.  
  1629.     sprintf( label, "Laps: %2d ", laps ) ;
  1630.     glCallLists( 9, GL_UNSIGNED_BYTE, label ) ;
  1631.     fontY -= fontDy ;
  1632.     glRasterPos2f( 5.0f, fontY ) ;
  1633.     if( ahead )
  1634.     {
  1635.         sprintf( label, "Ahead %2d laps", dLaps ) ;
  1636.         len = 13 ;
  1637.     }
  1638.     else
  1639.     {
  1640.         sprintf( label, "Back %2d laps", dLaps ) ;
  1641.         len = 12 ;
  1642.     }
  1643.     if( dLaps == 1 )
  1644.     {
  1645.         len-- ;
  1646.     }
  1647.     glCallLists( len, GL_UNSIGNED_BYTE, label ) ;
  1648.  
  1649.     fontY -= fontDy ;
  1650.     glRasterPos2f( 5.0f, fontY ) ;
  1651.     glCallLists( 6, GL_UNSIGNED_BYTE, "Time: " ) ;
  1652.     str = raceTimeString( t, &len ) ;
  1653.     glCallLists( len, GL_UNSIGNED_BYTE, str ) ;
  1654.  
  1655.     fontY -= fontDy ;
  1656.     glRasterPos2f( 5.0f, fontY ) ;
  1657.     glCallList( raceRecord ) ;
  1658.  
  1659. #ifdef DEBUG
  1660.     showFrameRate() ;
  1661. #endif /* DEBUG */
  1662.  
  1663.     if( cars[self].status & CAR_WIPE_OUT )
  1664.     {
  1665.         showRestartInfo() ;
  1666.     }
  1667.  
  1668.     drawIcons( position ) ;
  1669.  
  1670.     endOverlay() ;
  1671. }
  1672.  
  1673.  
  1674.  
  1675. /*------------------------------------------------------------------------------
  1676.  * Draw overlay for post trial run.
  1677.  *----------------------------------------------------------------------------*/
  1678. void
  1679. drawPostTrialOverlay(
  1680.     float    t,
  1681.     char    position[]
  1682.     )
  1683. {
  1684.     char    *str ;
  1685.     int    len ;
  1686.  
  1687.     beginOverlay() ;
  1688.  
  1689.     str = longRaceTimeString( t, &len ) ;
  1690.  
  1691.     glCallLists( 10, GL_UNSIGNED_BYTE, "Best Lap: "  ) ;
  1692.     glCallLists( len, GL_UNSIGNED_BYTE, str ) ;
  1693.  
  1694.     fontY -= fontDy ;
  1695.     glRasterPos2f( 5.0f, fontY ) ;
  1696.     glCallList( lapRecord ) ;
  1697.  
  1698.     drawIcons( position ) ;
  1699.  
  1700.     endOverlay() ;
  1701. }
  1702.  
  1703.  
  1704.  
  1705. /*------------------------------------------------------------------------------
  1706.  * Draw overlay for post race.
  1707.  *----------------------------------------------------------------------------*/
  1708. void
  1709. drawPostRaceOverlay(
  1710.     float    finishTime,
  1711.     float    raceTime,
  1712.     char    position[]
  1713.     )
  1714. {
  1715.     char    *str ;
  1716.     int    len ;
  1717.  
  1718.     beginOverlay() ;
  1719.  
  1720.     str = raceTimeString( finishTime, &len ) ;
  1721.  
  1722.     glCallLists( 12, GL_UNSIGNED_BYTE, "Final time: "  ) ;
  1723.     glCallLists( len, GL_UNSIGNED_BYTE, str ) ;
  1724.  
  1725.     fontY -= fontDy ;
  1726.     glRasterPos2f( 5.0f, fontY ) ;
  1727.     glCallList( raceRecord ) ;
  1728.  
  1729.     fontY -= fontDy ;
  1730.     str = raceTimeString( raceTime, &len ) ;
  1731.     glRasterPos2f( 5.0f, fontY ) ;
  1732.     glCallLists( 6, GL_UNSIGNED_BYTE, "Time: " ) ;
  1733.     glCallLists( len, GL_UNSIGNED_BYTE, str ) ;
  1734.  
  1735.     drawIcons( position ) ;
  1736.  
  1737.     endOverlay() ;
  1738. }
  1739.  
  1740.  
  1741.  
  1742. /*------------------------------------------------------------------------------
  1743.  * Set up for overlay drawing.
  1744.  *----------------------------------------------------------------------------*/
  1745. static void
  1746. beginOverlay(
  1747.     void
  1748.     )
  1749. {
  1750.     /*
  1751.      * Load identity matrix on the model view matrix.
  1752.      */
  1753.     glPushMatrix() ;
  1754.     glLoadIdentity() ;
  1755.  
  1756.     /*
  1757.      * Save the old projection matrix and initialize to ortho.
  1758.      */
  1759.     glMatrixMode( GL_PROJECTION ) ;
  1760.     glPushMatrix() ;
  1761.     glLoadIdentity() ;
  1762.  
  1763.     glOrtho( 0.0, raceViewWd, 0.0, raceViewHd, -1.0, 1.0 ) ;
  1764.  
  1765.     glColor3fv( white ) ;
  1766.  
  1767.     if( showSpeedBars )
  1768.         glCallList( speedBars ) ;
  1769.  
  1770.     fontY = raceViewH - olf->ascent - 2.0f ;
  1771.     glRasterPos2f( 5.0f, fontY ) ;
  1772. }
  1773.  
  1774.  
  1775.  
  1776. /*------------------------------------------------------------------------------
  1777.  * End overlay drawing.
  1778.  *----------------------------------------------------------------------------*/
  1779. static void
  1780. endOverlay(
  1781.     void
  1782.     )
  1783. {
  1784.     /*
  1785.      * Restore the old projection matrix.
  1786.      */
  1787.     glPopMatrix() ;
  1788.     /*
  1789.      * Restore the model view matrix.
  1790.      */
  1791.     glMatrixMode( GL_MODELVIEW ) ;
  1792.     glPopMatrix() ;
  1793. }
  1794.  
  1795.  
  1796.  
  1797. /*------------------------------------------------------------------------------
  1798.  * Give up the race.
  1799.  *----------------------------------------------------------------------------*/
  1800. static void
  1801. giveUp(
  1802.     Widget        w,
  1803.     XEvent        *event,
  1804.     String        *params,
  1805.     Cardinal    *numParams
  1806.     )
  1807. {
  1808.     giveUpRace() ;
  1809. }
  1810.  
  1811.  
  1812.  
  1813. /*------------------------------------------------------------------------------
  1814.  * Change the LOD setting.
  1815.  *----------------------------------------------------------------------------*/
  1816. static void
  1817. changeLod(
  1818.     Widget        w,
  1819.     XEvent        *event,
  1820.     String        *params,
  1821.     Cardinal    *numParams
  1822.     )
  1823. {
  1824.     baseLod = ( baseLod + 1 ) % MAX_LOD ;
  1825.  
  1826.     setCarBaseLod( baseLod ) ;
  1827.  
  1828.     setTrackBaseLod( baseLod ) ;
  1829.  
  1830.     setMessage( "LOD set to %d.", baseLod ) ;
  1831. }
  1832.  
  1833.  
  1834.  
  1835. /*------------------------------------------------------------------------------
  1836.  * Show instructions for restarting car after a wipeout.
  1837.  *----------------------------------------------------------------------------*/
  1838. static void
  1839. showRestartInfo(
  1840.     void
  1841.     )
  1842. {
  1843.     static char    *msg = "Place cursor below line to restart." ;
  1844.  
  1845.     glBegin( GL_LINES ) ;
  1846.     glVertex2f( 0.0f, 0.1f * raceViewH ) ;
  1847.     glVertex2f( raceViewW, 0.1f * raceViewH ) ;
  1848.     glEnd() ;
  1849.  
  1850.     glRasterPos2f( 5.0f, 0.1f * raceViewH + olf->descent + 2.0f ) ;
  1851.     glCallLists( 35, GL_UNSIGNED_BYTE, msg ) ;
  1852. }
  1853.  
  1854.  
  1855.  
  1856. /*------------------------------------------------------------------------------
  1857.  * Translation callback to end solo mode (debug).
  1858.  *----------------------------------------------------------------------------*/
  1859. static void
  1860. endSolo(
  1861.     Widget        w,
  1862.     XEvent        *event,
  1863.     String        *params,
  1864.     Cardinal    *numParams
  1865.     )
  1866. {
  1867.     endSoloGame() ;
  1868. }
  1869.  
  1870.  
  1871.  
  1872. /*------------------------------------------------------------------------------
  1873.  * Create the preview OpenGL widget.
  1874.  *----------------------------------------------------------------------------*/
  1875. void
  1876. createPreviewOglWidget(
  1877.     Widget        parent,
  1878.     Arg        pargs[],
  1879.     int        pn
  1880.     )
  1881. {
  1882.     int            n ;
  1883.     Arg            args[15] ;
  1884.  
  1885.     for( n = 0 ; n < pn ; n++ )
  1886.     {
  1887.         XtSetArg( args[n], pargs[n].name, pargs[n].value ) ;
  1888.     }
  1889.     XtSetArg( args[n], GLwNrgba, True ) ; n++ ;
  1890.     XtSetArg( args[n], GLwNdoublebuffer, True ) ; n++ ;
  1891.     XtSetArg( args[n], GLwNdepthSize, 16 ) ; n++ ;
  1892.     XtSetArg( args[n], GLwNredSize, 1 ) ; n++ ;
  1893.     XtSetArg( args[n], GLwNgreenSize, 1 ) ; n++ ;
  1894.     XtSetArg( args[n], GLwNblueSize, 1 ) ; n++ ;
  1895.     XtSetArg( args[n], GLwNinstallColormap, True ) ; n++ ;
  1896.     previewOgl = XtCreateManagedWidget( "previewOgl",
  1897.                 glwMDrawingAreaWidgetClass, parent, args, n ) ;
  1898.     XtAddCallback( previewOgl, GLwNexposeCallback,
  1899.                 (XtCallbackProc)drawPreviewCB, NULL ) ;
  1900.     XtAddCallback( previewOgl, GLwNresizeCallback,
  1901.             (XtCallbackProc)resizePreviewCB, NULL ) ;
  1902.     XtAddCallback( previewOgl, GLwNginitCallback,
  1903.             (XtCallbackProc)initPreviewCB, NULL ) ;
  1904. }
  1905.  
  1906.  
  1907.  
  1908. /*------------------------------------------------------------------------------
  1909.  * Callback for initialization - create GLXContext.
  1910.  *----------------------------------------------------------------------------*/
  1911. static void
  1912. initPreviewCB(
  1913.     Widget                w,
  1914.     XtPointer            clientData,
  1915.     GLwDrawingAreaCallbackStruct    *cbs
  1916.     )
  1917. {
  1918.     int        n ;
  1919.     Arg        args[1] ;
  1920.     XVisualInfo    *vi ;
  1921.  
  1922.     /*
  1923.      * Get GLXContext.
  1924.      */
  1925.     n = 0 ;
  1926.     XtSetArg( args[n], GLwNvisualInfo, &vi ) ; n++ ;
  1927.     XtGetValues( w, args, n ) ;
  1928.  
  1929.     previewGlc = glXCreateContext( XtDisplay( w ), vi, introGlc, GL_TRUE ) ;
  1930.     GLwDrawingAreaMakeCurrent( w, previewGlc ) ;
  1931.  
  1932.     glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ) ;
  1933.     glClearDepth( 1.0f ) ;
  1934.     glClear( GL_COLOR_BUFFER_BIT ) ;
  1935.     GLwDrawingAreaSwapBuffers( w ) ;
  1936.  
  1937.     glEnable( GL_DEPTH_TEST ) ;
  1938.  
  1939.     commonOglInit() ;
  1940.  
  1941.     /*
  1942.      * Set viewport and initialize viewing matrix.
  1943.      */
  1944.     resizePreviewCB( w, 0, cbs ) ;
  1945. }
  1946.  
  1947.  
  1948.  
  1949. /*------------------------------------------------------------------------------
  1950.  * Callback when resize occurs.
  1951.  *----------------------------------------------------------------------------*/
  1952. static void
  1953. resizePreviewCB(
  1954.     Widget                w,
  1955.     XtPointer            clientData,
  1956.     GLwDrawingAreaCallbackStruct    *cbs
  1957.     )
  1958. {
  1959.     if( previewGlc == NULL )
  1960.     {
  1961.         initPreviewCB( w, clientData, cbs ) ;
  1962.     }
  1963.     else if( previewGlc != NULL )
  1964.     {
  1965.         GLwDrawingAreaMakeCurrent( w, previewGlc ) ;
  1966.  
  1967.         glViewport( 0, 0, cbs->width, cbs->height ) ;
  1968.     }
  1969. }
  1970.  
  1971.  
  1972.  
  1973. /*------------------------------------------------------------------------------
  1974.  * Draw preview window.
  1975.  *----------------------------------------------------------------------------*/
  1976. static void
  1977. drawPreviewCB(
  1978.     Widget                w,
  1979.     XtPointer            clientData,
  1980.     GLwDrawingAreaCallbackStruct    *cbs
  1981.     )
  1982. {
  1983.     GLfloat        d ;
  1984.     GLfloat        x ;
  1985.     GLfloat        y ;
  1986.     GLfloat    bnds[8] ;
  1987.  
  1988.     if( previewGlc == NULL )
  1989.     {
  1990.         initPreviewCB( w, clientData, cbs ) ;
  1991.     }
  1992.     GLwDrawingAreaMakeCurrent( w, previewGlc ) ;
  1993.  
  1994.     glShadeModel( GL_FLAT ) ;
  1995.     glDisable( GL_DEPTH_TEST ) ;
  1996.     glDisable( GL_LIGHTING ) ;
  1997.  
  1998.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
  1999.  
  2000.     if( cbs->width > cbs->height )
  2001.     {
  2002.         x = (float)cbs->width / (float)cbs->height ;
  2003.         y = 1.0f ;
  2004.     }
  2005.     else
  2006.     {
  2007.         x = 1.0f ;
  2008.         y = (float)cbs->height / (float)cbs->width ;
  2009.     }
  2010.     getTrackBounds( bnds ) ;
  2011.  
  2012.     glMatrixMode( GL_PROJECTION ) ;
  2013.     glLoadIdentity() ;
  2014.     bnds[6] += 4.0f * LANE_WIDTH ;
  2015.     bnds[7] += 4.0f * LANE_WIDTH ;
  2016.     d = MAXFUNC( bnds[6], bnds[7] ) ;
  2017.     bnds[0] = bnds[4] - x * d ;
  2018.     bnds[1] = bnds[4] + x * d ;
  2019.     bnds[2] = bnds[5] - y * d ;
  2020.     bnds[3] = bnds[5] + y * d ;
  2021.     glOrtho( bnds[0], bnds[1], bnds[2], bnds[3], -1.0, 1.0 ) ;
  2022.  
  2023.     glMatrixMode( GL_MODELVIEW ) ;
  2024.     glLoadIdentity() ;
  2025.     glCallList( trackOutline ) ;
  2026.  
  2027.     GLwDrawingAreaSwapBuffers( w ) ;
  2028. }
  2029.  
  2030.  
  2031.  
  2032. /*------------------------------------------------------------------------------
  2033.  * Show an arrow above player's car.
  2034.  *----------------------------------------------------------------------------*/
  2035. static void
  2036. showArrow(
  2037.     void
  2038.     )
  2039. {
  2040.     glPushMatrix() ;
  2041.     glCallList( mainSet ) ;
  2042.     if( rearView )
  2043.     {
  2044.         glScalef( -1.0f, 1.0f, 1.0f ) ;
  2045.     }
  2046.     glCallList( arrow ) ;
  2047.     glPopMatrix() ;
  2048. }
  2049.  
  2050.  
  2051.  
  2052. /*------------------------------------------------------------------------------
  2053.  * Return the width of a string.
  2054.  *----------------------------------------------------------------------------*/
  2055. static int
  2056. getStrWidth(
  2057.     VroomFont    *vf,
  2058.     char        *str,
  2059.     int        len
  2060.     )
  2061. {
  2062.     return( XTextWidth( vf->xfont, str, len ) ) ;
  2063. }
  2064.  
  2065.  
  2066.  
  2067. /*------------------------------------------------------------------------------
  2068.  * Display the list of players.
  2069.  *----------------------------------------------------------------------------*/
  2070. static void
  2071. showPlayers(
  2072.     Widget        w,
  2073.     XEvent        *event,
  2074.     String        *params,
  2075.     Cardinal    *numParams
  2076.     )
  2077. {
  2078.     static char    *hs = "human" ;
  2079.     static char    *rs = "robot" ;
  2080.  
  2081.     if( playMode == VROOM_TEAM )
  2082.     {
  2083.         postInfo( NULL, NULL,
  2084.             "Red: %s (%s)\n\n"
  2085.             "Green: %s (%s)\n\n"
  2086.             "Blue: %s (%s)\n\n"
  2087.             "Yellow: %s (%s)\n\n"
  2088.             "Pink: %s (%s)\n\n"
  2089.             "Cyan: %s (%s)\n\n"
  2090.             "Orange: %s (%s)\n\n"
  2091.             "White: %s (%s)",
  2092.             cars[0].name, ( isRobot[0] ? rs : hs ),
  2093.             cars[1].name, ( isRobot[1] ? rs : hs ),
  2094.             cars[2].name, ( isRobot[2] ? rs : hs ),
  2095.             cars[3].name, ( isRobot[3] ? rs : hs ),
  2096.             cars[4].name, ( isRobot[4] ? rs : hs ),
  2097.             cars[5].name, ( isRobot[5] ? rs : hs ),
  2098.             cars[6].name, ( isRobot[6] ? rs : hs ),
  2099.             cars[7].name, ( isRobot[7] ? rs : hs ) ) ;
  2100.     }
  2101. }
  2102.  
  2103.  
  2104.  
  2105. /*------------------------------------------------------------------------------
  2106.  * Print out the frame rate.
  2107.  *----------------------------------------------------------------------------*/
  2108. static void
  2109. showFrameRate(
  2110.     void
  2111.     )
  2112. {
  2113.     char    fr[6] ;
  2114.  
  2115.     fontY -= fontDy ;
  2116.     glRasterPos2f( 5.0f, fontY ) ;
  2117.     sprintf( fr, "%.1f", frameRate ) ;
  2118.     glCallLists( strlen( fr ), GL_UNSIGNED_BYTE, fr ) ;
  2119. }
  2120.  
  2121.  
  2122.  
  2123. /*------------------------------------------------------------------------------
  2124.  * Set up cull view.
  2125.  *----------------------------------------------------------------------------*/
  2126. static void
  2127. setUpCull(
  2128.     void
  2129.     )
  2130. {
  2131.     float    ci ;
  2132.     float    ca ;
  2133.     float    e[3] ;
  2134.     float    vl[3] ;
  2135.     float    vw[3] ;
  2136.     float    vh[3] ;
  2137.     float    s ;
  2138.     float    ang ;
  2139.  
  2140.     ci = 750.0f * cosIncl ;
  2141.     ca = cosAzim * ci ;
  2142.  
  2143.     ang = player[self].headingDeg * DEG_2_RAD ;
  2144.     vl[0] = -sinf( ang ) ;
  2145.     vl[1] = cosf( ang ) ;
  2146.     vl[2] = -750.0f * sinIncl ;
  2147.  
  2148.     e[0] = player[self].x - ( lead + ca ) * vl[0] ;
  2149.     e[1] = player[self].y - ( lead + ca ) * vl[1] ;
  2150.     e[2] = -vl[2] ;
  2151.  
  2152.     vl[0] *= ca ;
  2153.     vl[1] *= ca ;
  2154.  
  2155.     s = 1.0f / sqrtf( vl[0] * vl[0] + vl[1] * vl[1] + vl[2] * vl[2] ) ;
  2156.     vl[0] *= s ;
  2157.     vl[1] *= s ;
  2158.     vl[2] *= s ;
  2159.  
  2160.     vw[0] = vl[1] ;
  2161.     vw[1] = -vl[0] ;
  2162.     vw[2] = 0.0f ;
  2163.     s = 1.0f / sqrtf( vw[0] * vw[0] + vw[1] * vw[1] ) ;
  2164.     vw[0] *= s ;
  2165.     vw[1] *= s ;
  2166.  
  2167.     vh[0] = vw[1] * vl[2] - vw[2] * vl[1] ;
  2168.     vh[1] = vw[2] * vl[0] - vw[0] * vl[2] ;
  2169.     vh[2] = vw[0] * vl[1] - vw[1] * vl[0] ;
  2170.  
  2171.     qcSetView( e, vl, vw, vh ) ;
  2172. }
  2173.  
  2174.  
  2175.  
  2176. /*------------------------------------------------------------------------------
  2177.  * Create the star background.
  2178.  *----------------------------------------------------------------------------*/
  2179. static void
  2180. createStars(
  2181.     void
  2182.     )
  2183. {
  2184.     int        i ;
  2185.     int        j ;
  2186.     int        k ;
  2187.     int        n ;
  2188.     int        rndMask = 0x0fff ;
  2189.     float        rndDiv = 1.0f / 4095.0f ;
  2190.     float        phi ;
  2191.     float        phi0 ;
  2192.     float        phi1 ;
  2193.     float        phiFactor ;
  2194.     float        theta ;
  2195.     float        theta0 ;
  2196.     float        theta1 ;
  2197.     float        thetaFactor ;
  2198.     float        dS ;
  2199.     float        S ;
  2200.     const int    nTheta = 11 ;
  2201.     const int    nPhi = 5 ;
  2202.     const int    nStars = 150 ;
  2203.  
  2204.     thetaFactor = 360.0f * DEG_2_RAD / (float)( nTheta ) ;
  2205.     phiFactor = 85.0f * DEG_2_RAD / (float)( nPhi ) ;
  2206.     stars = glGenLists( MAX_LOD ) ;
  2207.  
  2208.     /*
  2209.      * Find total surface size of star display area.
  2210.      */
  2211.     S = ( sinf( 15.0f * DEG_2_RAD ) - sinf( -70.0f * DEG_2_RAD ) ) *
  2212.         2.0f * (float)M_PI ;
  2213.  
  2214.     for( i = MAX_LOD - 1 ; i >= 0 ; i-- )
  2215.     {
  2216.         glNewList( stars+i, GL_COMPILE ) ;
  2217.         if( i == MAX_LOD - 1 )
  2218.         {
  2219.             glColor3f( 1.0f, 1.0f, 1.0f ) ;
  2220.         }
  2221.         for( n = i + 1 ; n < MAX_LOD ; n++ )
  2222.         {
  2223.             glCallList( stars + n ) ;
  2224.         }
  2225.         glBegin( GL_POINTS ) ;
  2226.         for( j = 0 ; j < nTheta ; j++ )
  2227.         {
  2228.             theta0 = j * thetaFactor ;
  2229.             theta1 = theta0 + thetaFactor ;
  2230.             for( k = 0 ; k < nPhi ; k++ )
  2231.             {
  2232.                 phi0 = -70.0f * DEG_2_RAD + k * phiFactor ;
  2233.                 phi1 = phi0 + phiFactor ;
  2234.                 dS = ( sinf( phi1 ) - sinf( phi0 ) ) *
  2235.                     ( theta1 - theta0 ) ;
  2236.                 /*
  2237.                  * Calculate how many stars in this quadrant.
  2238.                  * (Avoids clustering of stars near poles.)
  2239.                  */
  2240.                 n = (int)( (float)nStars * dS / S ) ;
  2241.                 while( n-- > 0 )
  2242.                 {
  2243.                     theta = ( rand() & rndMask ) * rndDiv ;
  2244.                     theta = theta0 +
  2245.                         theta * ( theta1 - theta0 ) ;
  2246.                     phi = ( rand() & rndMask ) * rndDiv ;
  2247.                     phi = phi0 + phi * ( phi1 - phi0 ) ;
  2248.                     glVertex3f( 1000.f * cosf(phi) *
  2249.                                 cosf(theta),
  2250.                             1000.0f * cosf( phi ) *
  2251.                                 sinf( theta ),
  2252.                             1000.0f * sinf( phi ) ) ;
  2253.                 }
  2254.             }
  2255.         }
  2256.         glEnd() ;
  2257.         glEndList() ;
  2258.     }
  2259. }
  2260.  
  2261.  
  2262.  
  2263. /*------------------------------------------------------------------------------
  2264.  * Create display lists for printing out the track lap and race records.
  2265.  *----------------------------------------------------------------------------*/
  2266. void
  2267. noteTrackRecords(
  2268.     void
  2269.     )
  2270. {
  2271.     char    *str ;
  2272.     int    len ;
  2273.     static char    *r = "Record: " ;
  2274.  
  2275.     str = longRaceTimeString( getTrackLapRecordTime(), &len ) ;
  2276.     glNewList( lapRecord, GL_COMPILE ) ;
  2277.     glCallLists( 8, GL_UNSIGNED_BYTE, r ) ;
  2278.     glCallLists( len, GL_UNSIGNED_BYTE, str ) ;
  2279.     glEndList() ;
  2280.  
  2281.     str = longRaceTimeString( getTrackRaceRecordTime(), &len ) ;
  2282.     glNewList( raceRecord, GL_COMPILE ) ;
  2283.     glCallLists( 8, GL_UNSIGNED_BYTE, r ) ;
  2284.     glCallLists( len, GL_UNSIGNED_BYTE, str ) ;
  2285.     glEndList() ;
  2286. }
  2287.